package data;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Scanner;

import static conf.Configuration.*;

/**
 * Reads data in from a given comma-separated-value (CSV) file, creating a list of students.
 * @author Maxime Serrano
 */
public class StudentDataReader
{	
	// These are the positions in the split array of each type.
	private static final int RESPONSE_POS = 0;
	private static final int SUBMISSION_DATE_POS = 1;
	private static final int STUDENT_ID_POS = 2;
	private static final int STUDENT_NAME_POS = 3;
	private static final int STUDENT_USERNAME_POS = 4;
	private static final int STUDENT_TEACHER_POS = 5;
	private static final int ON_TRIP_POS = 6;
	private static final int STUDENT_GENDER_POS = 7;
	private static final int STUDENT_GRADE_POS = 8;
	private static final int START_CLASS_CHOICES = 9;
	private static final int LAST_CLASS_CHOICE = START_CLASS_CHOICES + REAL_NUM_CLASS_CHOICES;
	
	private static final String DELIMITER = ",";
	
	private static final String LATE_STRING = "LATE";
	private static final String NO_STRING = "No";
	private static final String MALE_STRING = "Male";
	private static final String SENIOR_STRING = "Senior";
	private static final String JUNIOR_STRING = "Junior";
	private static final String SOPHOMORE_STRING = "Sophomore";
	private static final String COURSE_ID_IDENTIFIER = "KS";
	private static final int ID_STRING_LENGTH = 2;
	
	// self-explanatory
	private ArrayList<Student> students = new ArrayList<Student>();
	private final String fileName;
	
	/**
	 * Creates a new data reader using the default file name. This default is "Knight_School_Signups.csv".
	 */
	public StudentDataReader()
	{
		this.fileName = DEFAULT_STUDENT_FILE_NAME;
	}
	
	/**
	 * Creates a new data reader using the given file name.
	 * @param fileName The .csv file to read in student data from.
	 */
	public StudentDataReader(String fileName)
	{
		this.fileName = fileName;
	}

	/**
	 * Creates the ArrayList of students in order to begin the reading.
	 */
	public void read()
	{
		Scanner s = null;
		try
		{
			s = new Scanner(new BufferedReader(new FileReader(fileName)));
			while(s.hasNext())
			{
				String[] line = s.nextLine().split(DELIMITER);
				if(true)
				{
					StudentData st = new StudentData();
					st.response = Integer.parseInt(line[RESPONSE_POS]);
					st.submissionDate = line[SUBMISSION_DATE_POS];
					
					if(st.submissionDate.equals(LATE_STRING))
					{
						st.studentID = -1;
						st.isLate = true;
					}
					else
					{
						try
						{
							st.studentID = Integer.parseInt(line[STUDENT_ID_POS]);
						}
						catch(NumberFormatException e)
						{
							st.studentID = -1;
						}
						st.isLate = false;
					}
					
					st.studentName = line[STUDENT_NAME_POS];
					st.studentUser = line[STUDENT_USERNAME_POS];
					st.studentTeacher = !(line[STUDENT_TEACHER_POS].equalsIgnoreCase(NO_STRING));
					st.onTrip = !(line[ON_TRIP_POS].equalsIgnoreCase(NO_STRING));
					st.isMale = line[STUDENT_GENDER_POS].equalsIgnoreCase(MALE_STRING);
					
					// Deals with the grade.
					st.grade = Grade.FRESHMAN;
					String gr = line[STUDENT_GRADE_POS];
					
					if (gr.equalsIgnoreCase(SENIOR_STRING))
					{
						st.grade = Grade.SENIOR;
					}
					else if (gr.equalsIgnoreCase(JUNIOR_STRING))
					{
						st.grade = Grade.JUNIOR;
					}
					else if (gr.equalsIgnoreCase(SOPHOMORE_STRING))
					{
						st.grade = Grade.SOPHOMORE;
					}
					
					st.classChoices = new int[REAL_NUM_CLASS_CHOICES];
					for (int index = START_CLASS_CHOICES, i = 0; index < LAST_CLASS_CHOICE; index++, i++)
					{
						if (index < line.length)
						{
							try
							{
								// If blank, no choice.
								if (line[index].length() < 4)
								{
									st.classChoices[i] = -1;
								}
								else
								{
									// Just in case the ID is weirdly placed
									final int START_ID = line[index].indexOf(COURSE_ID_IDENTIFIER) + COURSE_ID_IDENTIFIER.length();
									final int END_ID = START_ID + ID_STRING_LENGTH;
									st.classChoices[i] = Integer.parseInt(line[index].substring(START_ID, END_ID));
								}
							}
							catch (java.lang.NumberFormatException e)
							{
								// If they're on a trip.
								st.classChoices[i] = -1;
							}
						}
						else
						{
							st.classChoices[i] = -1;
						}
					}
					
					students.add(new Student(st));
				}
			}
		}
		catch (FileNotFoundException e) // FAIL
		{
			System.err.println("Student data input file not found!");
			e.printStackTrace();
		}
		catch (Exception e)
		{
			System.err.println("Unknown exception occurred while reading student data!");
			e.printStackTrace();
		}
		finally
		{
			if (s != null)
			{
				s.close();
			}
		}
	}
	
	/**
	 * Returns a new copy of the read data as an array list.
	 * @return An array list of all students that have currently been read in.
	 */
	public ArrayList<Student> getAsList()
	{
		return new ArrayList<Student>(students);
	}
}
